package com.spring;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
 * spring spel表达式解析测试
 * 
 * @author user
 *
 */
public class SpelParser {

	static ExpressionParser parser = new SpelExpressionParser();

	static void testSpel() {
		class Simple {
			public List<Boolean> booleanList = new ArrayList<Boolean>();
		}

		Simple simple = new Simple();

		simple.booleanList.add(true);

		StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple);

		// false is passed in here as a string. SpEL and the conversion service
		// will
		// correctly recognize that it needs to be a Boolean and convert it
		parser.parseExpression("booleanList[0]").setValue(simpleContext, "false");

		// b will be false
		Boolean b = simple.booleanList.get(0);

		System.out.println(b);

		class User {
			private String userName;

			private String[] emails;

			private String firstName;

			private String middleName;
			private String lastName;

			public String getUserName() {
				return userName;
			}

			public void setUserName(String userName) {
				this.userName = userName;
			}

			public String[] getEmails() {
				return emails;
			}

			public void setEmails(String[] emails) {
				this.emails = emails;
			}

			public String getFirstName() {
				return firstName;
			}

			public void setFirstName(String firstName) {
				this.firstName = firstName;
			}

			public String getMiddleName() {
				return middleName;
			}

			public void setMiddleName(String middleName) {
				this.middleName = middleName;
			}

			public String getLastName() {
				return lastName;
			}

			public void setLastName(String lastName) {
				this.lastName = lastName;
			}

		}

		class Form {
			private User user;

			public User getUser() {
				return user;
			}

			public void setUser(User user) {
				this.user = user;
			}

		}

		User user = new User();
		user.setFirstName("li");
		user.setMiddleName("huan");
		user.setLastName("huan");
		StandardEvaluationContext simpleContext2 = new StandardEvaluationContext();
		simpleContext2.setVariable("user", user);
		parser.parseExpression("#user.userName").setValue(simpleContext2, "lihuanhuan");
		System.out.println("1. " + user.getUserName());
		
		

		StandardEvaluationContext simpleContext21 = new StandardEvaluationContext(user);
		parser.parseExpression("userName").setValue(simpleContext21, "lihuanhuan");
		System.out.println("21. " + user.getUserName());
		

		// Turn on:
		// - auto null reference initialization
		// - auto collection growing
		SpelParserConfiguration config = new SpelParserConfiguration(true, true);
		ExpressionParser parser1 = new SpelExpressionParser(config);
		Form form = new Form();
		form.setUser(new User());
		StandardEvaluationContext simpleContext3 = new StandardEvaluationContext(form);
		parser1.parseExpression("user.userName").setValue(simpleContext3, "lihuanhuan");
		System.out.println("2. " + form.getUser().getUserName());

		// Map<String,Object> map = new HashMap();
		// map.put("user", user);
		// StandardEvaluationContext simpleContext3 = new
		// StandardEvaluationContext(map);
		// parser.parseExpression("user.userName").setValue(simpleContext3,
		// "lihuanhuan");
		// System.out.println(user.getUserName());

		class Person {
			private String name;
			private int age;

			public Person(String name, int age) {
				super();
				this.name = name;
				this.age = age;
			}

			public String getName() {
				return name;
			}

			public void setName(String name) {
				this.name = name;
			}

			public int getAge() {
				return age;
			}

			public void setAge(int age) {
				this.age = age;
			}

			@Override
			public String toString() {
				return "Person {" + name + "," + age + "}";
			}

		}
		ExpressionParser parser = new SpelExpressionParser();

		Person person = new Person("fsx", 30);
		List<String> list = new ArrayList<String>() {
			{
				add("fsx");
				add("周杰伦");
			}
		};
		Map<String, Integer> map = new HashMap<String, Integer>() {
			{
				put("fsx", 18);
				put("周杰伦", 40);
			}
		};

		EvaluationContext ctx = new StandardEvaluationContext();
		// 把list和map都放进环境变量里面去
		ctx.setVariable("myPerson", person);
		ctx.setVariable("myList", list);
		ctx.setVariable("myMap", map);

		// ============================================
		System.out.println(parser.parseExpression("#myPerson").getValue(ctx)); // Person{name='fsx',
																				// age=30}
		System.out.println(parser.parseExpression("#myPerson.name").getValue(ctx)); // fsx
		// setVariable方式取值不能像root一样，前缀不可省略~~~~~
		System.out.println(parser.parseExpression("#name").getValue(ctx)); // null
																			// 显然找不到这个key就返回null呗~~~
		// 不写前缀默认去root找，找出一个null。再访问name属性那可不报错了吗
		// System.out.println(parser.parseExpression("name").getValue(ctx)); //
		// Property or field 'name' cannot be found on null

		System.out.println(parser.parseExpression("#myList").getValue(ctx)); // [fsx,
																				// 周杰伦]
		System.out.println(parser.parseExpression("#myList[1]").getValue(ctx)); // 周杰伦

		// 请注意对Map取值两者的区别：中文作为key必须用''包起来 当然['fsx']也是没有问题的
		System.out.println(parser.parseExpression("#myMap[fsx]").getValue(ctx)); // 18
		System.out.println(parser.parseExpression("#myMap['周杰伦']").getValue(ctx)); // 40
		System.out.println(parser.parseExpression("#myMap['周杰伦'] + #myMap[fsx]").getValue(ctx)); // 58

		// 黑科技：SpEL内直接可以使用new方式创建实例 能创建数组、List 但不能创建普通的实例对象（难道是我还不知道）~~~~
		System.out.println(parser.parseExpression("new String[]{'java','spring'}").getValue()); // [Ljava.lang.String;@30b8a058
		System.out.println(parser.parseExpression("{'java','c语言','PHP'}").getValue()); // [java,
																						// c语言,
																						// PHP]
																						// 创建List
		System.out.println(parser.parseExpression("new Person()").getValue()); // A
																				// problem
																				// occurred
																				// whilst
																				// attempting
																				// to
																				// const

	}

	public static void main(String[] args) {
		Expression exp = parser.parseExpression("'Hello World'");
		String message = (String) exp.getValue();
		System.out.println(message);

		testSpel();
	}

}
